package org.etom.impl.ui.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.ui.IMemento;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.XMLMemento;
import org.etom.connector.datatypes.IMoodleConnection;
import org.etom.connector.service.ConnectorException;
import org.etom.connector.service.MoodleConnector;
import org.etom.impl.ui.Activator;
import org.osgi.framework.BundleContext;

/**
 * The class is responsible for the storing of the connections.
 */
public class ConnectionStorage {
  
  private static final String STORAGE_FILE                   = "moodle.connection.storage"; //$NON-NLS-1$
  private static final IMoodleConnection[] EMPTY_CONNECTIONS = new IMoodleConnection[0];
  
  private static final String CONNECTIONS_ROOT = "moodle_connections"; //$NON-NLS-1$
  private static final String CONNECTION_TYPE  = "moodle_connection"; //$NON-NLS-1$
  private static final String CONNECTION_MOODLE_URL     = "moodle_connection_moodle_url"; //$NON-NLS-1$
  private static final String CONNECTION_RPC_SERVER_URL = "moodle_connection_rpc_server_url"; //$NON-NLS-1$
  private static final String CONNECTION_USERNAME       = "moodle_connection_username"; //$NON-NLS-1$
  private static final String CONNECTION_PASSWORD       = "moodle_connection_password"; //$NON-NLS-1$

  private BundleContext context;
  
  /**
   * Constructs the connection storage.
   * 
   * @param context - the bundle context which will be used to access the data storage file.
   */
  public ConnectionStorage(BundleContext context) {
    if (null == context) throw new NullPointerException(CommonMessages.Bundle_Context_Null);
    this.context = context;
  }
  
  /**
   * The method loads the connection storage data.
   * 
   * @return - all loaded connections
   * 
   * @throws WorkbenchException - if the connections can not be loaded
   */
  public IMoodleConnection[] load() throws WorkbenchException {
    File storageFile = context.getDataFile(STORAGE_FILE);
    if (!storageFile.exists()) return EMPTY_CONNECTIONS;
    XMLMemento memento = null;
    try {
      memento = XMLMemento.createReadRoot(new FileReader(storageFile));
    } catch (FileNotFoundException fnfe) {
      return EMPTY_CONNECTIONS;
    }
    List<IMoodleConnection> connections = load(memento);
    return connections.toArray(new IMoodleConnection[connections.size()]);
  }
  
  /**
   * The method stores the connections.
   * 
   * @param connections - the connections which will be stored
   * 
   * @throws IOException - if the connections can not be stored
   */
  public void save(IMoodleConnection[] connections) throws IOException {
    File storageFile = context.getDataFile(STORAGE_FILE);
    if (storageFile.exists()) storageFile.delete();
    XMLMemento rootMemento = XMLMemento.createWriteRoot(CONNECTIONS_ROOT);
    IMemento currentMemento;
    for (IMoodleConnection connection : connections) {
      currentMemento = rootMemento.createChild(CONNECTION_TYPE);
      currentMemento.putString(CONNECTION_MOODLE_URL, connection.getMoodleUrl());
      currentMemento.putString(CONNECTION_RPC_SERVER_URL, connection.getRpcServerUrl());
      currentMemento.putString(CONNECTION_USERNAME, connection.getUserName());
      currentMemento.putString(CONNECTION_PASSWORD, Utility.encrypt(connection.getPassword()));
    }
    rootMemento.save(new FileWriter(storageFile));
  }
  
  /*
   * The utility method loads the connections from Memento.
   */
  //FIXME: synchronize with the write operation
  private List<IMoodleConnection> load(IMemento memento) {
    IMemento[] storedConnections = memento.getChildren(CONNECTION_TYPE);
    MoodleConnector connector = Activator.getDefault().getMoodleConnector();
    List<IMoodleConnection> result = new ArrayList<IMoodleConnection>(10);
    try {
      for (IMemento currentConnection : storedConnections) {
        result.add(connector.getConnection(
            currentConnection.getString(CONNECTION_MOODLE_URL),
            currentConnection.getString(CONNECTION_RPC_SERVER_URL),
            currentConnection.getString(CONNECTION_USERNAME),
            Utility.decrypt(currentConnection.getString(CONNECTION_PASSWORD))));
      }
    } catch (ConnectorException ce) {
      //nothing to do here, we read the stored connections
    }
    return result;
  }
  
}
